# 1.    Web应用的搭建功能性约束
# 1)    依赖管理
# 确保所有必要的库都已安装：包括numpy, flask, tensorflow, keras等。
# 此外，还需要确保cifar100_vgg16模块可用且正确导入。
import numpy as np
from flask import Flask, render_template, request
from keras.preprocessing.image import load_img, img_to_array

app = Flask(__name__)
# 2)    模型加载与构建
# 模型文件存在：确保model.h5文件存在于应用的根目录或指定的路径下，并且该模型是有效的CIFAR-100 VGG16模型。
# 模型正确加载：在Flask应用中，模型需要在服务请求之前正确加载和构建。

import vgg16

new_model = vgg16.VGG16()
new_model.build(input_shape=(None, 32, 32, 3))
new_model.load_weights('model.h5')


# 3)    图像处理
# 支持的文件类型：应用应能处理通过HTTP POST请求上传的图像文件，主要支持图像格式如JPEG, PNG等。
# 图像预处理：上传的图像需要被正确加载、转换为数组、调整大小并归一化到[0, 1]范围内。
@app.route('/')
def hello():
    return render_template('home.html')


def read_img(path):
    img = load_img(path, target_size=(32, 32), grayscale=False)
    img = img_to_array(img)
    img = img.reshape(-1, 32, 32, 3) / 255
    return img


# 4)    预测功能
# 准确的预测：模型应能接收预处理后的图像数据，并返回准确的预测类别。
# 类别映射：需要一个准确的类别映射（如product_dict），以便将模型输出的类别索引转换为人类可读的标签。

# 5)    用户界面
# HTML模板：应用应包含home.html和predict.html两个HTML模板文件，分别用于显示主页和预测结果。
# 文件上传：home.html应包含一个文件上传表单，允许用户上传图像文件。
# 结果显示：predict.html应能显示预测结果和用户上传的图像。
@app.route('/predict', methods=['GET', 'POST'])
def predict():
    try:
        if request.method == 'POST':
            file = request.files['file']
            if file:
                file_name = file.filename
                path = f'static/{file_name}'
                file.save(path)
                img = read_img(path)
                predict = new_model.predict(img)
                label = np.argmax(predict)
                product_dict = {
                    0: 'apple',
                    1: 'aquarium_fish',
                    2: 'baby',
                    3: 'bear',
                    4: 'beaver',
                    5: 'bed',
                    6: 'bee',
                    7: 'beetle',
                    8: 'bicycle',
                    9: 'bottle',
                    10: 'bowl',
                    11: 'boy',
                    12: 'bridge',
                    13: 'bus',
                    14: 'butterfly',
                    15: 'camel',
                    16: 'can',
                    17: 'castle',
                    18: 'caterpillar',
                    19: 'cattle',
                    20: 'chair',
                    21: 'chimpanzee',
                    22: 'clock',
                    23: 'cloud',
                    24: 'cockroach',
                    25: 'couch',
                    26: 'crab',
                    27: 'crocodile',
                    28: 'cup',
                    29: 'dinosaur',
                    30: 'dolphin',
                    31: 'elephant',
                    32: 'flatfish',
                    33: 'forest',
                    34: 'fox',
                    35: 'girl',
                    36: 'hamster',
                    37: 'house',
                    38: 'kangaroo',
                    39: 'keyboard',
                    40: 'lamp',
                    41: 'lawn_mower',
                    42: 'leopard',
                    43: 'lion',
                    44: 'lizard',
                    45: 'lobster',
                    46: 'man',
                    47: 'maple_tree',
                    48: 'motorcycle',
                    49: 'mountain',
                    50: 'mouse',
                    51: 'mushroom',
                    52: 'oak_tree',
                    53: 'orange',
                    54: 'orchid',
                    55: 'otter',
                    56: 'palm_tree',
                    57: 'pear',
                    58: 'pickup_truck',
                    59: 'pine_tree',
                    60: 'plain',
                    61: 'plate',
                    62: 'poppy',
                    63: 'porcupine',
                    64: 'possum',
                    65: 'rabbit',
                    66: 'raccoon',
                    67: 'ray',
                    68: 'road',
                    69: 'rocket',
                    70: 'rose',
                    71: 'sea',
                    72: 'seal',
                    73: 'shark',
                    74: 'shrew',
                    75: 'skunk',
                    76: 'skyscraper',
                    77: 'snail',
                    78: 'snake',
                    79: 'spider',
                    80: 'squirrel',
                    81: 'streetcar',
                    82: 'sunflower',
                    83: 'sweet_pepper',
                    84: 'table',
                    85: 'tank',
                    86: 'telephone',
                    87: 'television',
                    88: 'tiger',
                    89: 'tractor',
                    90: 'train',
                    91: 'trout',
                    92: 'tulip',
                    93: 'turtle',
                    94: 'wardrobe',
                    95: 'whale',
                    96: 'willow_tree',
                    97: 'wolf',
                    98: 'woman',
                    99: 'worm'
                }
                return render_template('predict.html', path=path, product=product_dict[label])
        else:
            return render_template('predict.html')
    except Exception:
        return str(Exception)


# 6)    错误处理
# 异常处理：应捕获并处理所有可能发生的异常，如文件上传错误、模型加载错误、预测错误等，并向用户提供友好的错误信息。
# 7)    安全性
# 数据保护：确保用户上传的数据（如图像文件）在服务器上得到妥善处理，避免数据泄露。
# 8)    性能
# 响应时间：确保应用能够快速响应用户的请求，特别是在进行图像处理和模型预测时。
# 资源使用：监控应用的资源使用情况，确保不会因为处理大量请求而导致资源耗尽。
# 9)    调试
# 启用调试模式：在开发过程中，应启用Flask的调试模式以获取更详细的错误信息。
# 10)    部署
# 服务器配置：确保应用能够在目标服务器上正确配置和部署，包括必要的依赖和环境设置。
# 端口配置：确保Flask应用监听的端口（如6008）在服务器上未被其他服务占用。
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=6008, debug=True)